package Accessors;

import java.io.IOException;
import java.util.ArrayList;

import org.json.JSONException;
import org.json.JSONObject;

import utils.RESTfulConnect;
import utils.URLTools;
import Callbacks.AbstractCallback;
import Enums.RFAT;
import Presenter.AbstractPresenter;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;

@SuppressWarnings("rawtypes")
public abstract class AbstractAccessor<T,U extends AbstractPresenter,C extends AbstractCallback> {
	private U presenter;
	private C callback;
	
	//Modal dialog variable.
	ProgressDialog modalDialog = null;

    public AbstractAccessor(U u, C c) {
    	this.presenter = u;
    	this.callback = c;
    }
    
    public void getAllItems(final Context context, final String dialog, final String str){
		modalDialog = ProgressDialog.show(context, null, dialog);
		final String strStart = URLTools.getURLString(context);
		new DownloadAllItemsTask().execute(strStart+str, URLTools.getUSERString(context), URLTools.getPASSString(context));
	}
	
	public void getItem(final Context context, final String dialog, final String str){
		modalDialog = ProgressDialog.show(context, null, dialog);
		final String strStart = URLTools.getURLString(context);
		new DownloadItemTask().execute(strStart+str, URLTools.getUSERString(context), URLTools.getPASSString(context));
	}
	
	public void deleteItem(final Context context, final String dialog, final String str){
		modalDialog = ProgressDialog.show(context, null, dialog);
		final String strStart = URLTools.getURLString(context);
		new DeleteItemTask().execute(strStart+str, URLTools.getUSERString(context), URLTools.getPASSString(context));
	}
    
    @SuppressWarnings("unchecked")
	public void getAllItems(final T item, final Context context, final String dialog, final String str){
		modalDialog = ProgressDialog.show(context, null, dialog);
		final String strStart = URLTools.getURLString(context);
		new DownloadAllItemsTask().execute(strStart+str, URLTools.getUSERString(context), URLTools.getPASSString(context), presenter.createJSON(item).toString());
	}
	
	@SuppressWarnings("unchecked")
	public void doItemUpdate(final T item, final Context context, final String dialog, final String str){
		modalDialog = ProgressDialog.show(context, null, dialog);
		final String strStart = URLTools.getURLString(context);
		new UpdateItemTask().execute(strStart+str, URLTools.getUSERString(context), URLTools.getPASSString(context), presenter.createJSON(item).toString());
	}
	
	@SuppressWarnings("unchecked")
	public void doItemInsert(final T item, final Context context, final String dialog, final String str){
		modalDialog = ProgressDialog.show(context, null, dialog);
		final String strStart = URLTools.getURLString(context);
		new InsertItemTask().execute(strStart+str, URLTools.getUSERString(context), URLTools.getPASSString(context), presenter.createJSON(item).toString());
	}
	
	//Asynch tasks for functions.
	private class DownloadAllItemsTask extends AsyncTask<String, Void, String> {
    	@Override
        protected String doInBackground(String... urls) {
            try {
                return RESTfulConnect.getResource(urls[0], urls[1], urls[2]);
            } catch (IOException e) {
            	e.printStackTrace();
            	return "Connection Error";
            }
        }
    	@SuppressWarnings("unchecked")
		@Override
        protected void onPostExecute(String result) {
    		modalDialog.dismiss();
    		ArrayList<T> items = presenter.tryJSONParseArray(result);
    		if(items != null){
		    	T t = items.get(0);
		    	callback.callback(t, RFAT.GET_LIST, items);
    		} else {
    			T t = (T)presenter.getEmptyEntity();
        		ArrayList<T> itms = new ArrayList<T>();
		    	callback.callback(t, RFAT.GET_LIST, itms);
    		}
        }
    }
	
	private class DownloadItemTask extends AsyncTask<String, Void, String> {
    	@Override
        protected String doInBackground(String... urls) {

            try {
                return RESTfulConnect.getResource(urls[0], urls[1], urls[2]);
            } catch (IOException e) {
            	e.printStackTrace();
            	return "Connection Error";
            }
        }
    	@SuppressWarnings("unchecked")
		@Override
        protected void onPostExecute(String result) {
    		T t = (T)presenter.tryJSONParse(result);
    		modalDialog.dismiss();
    		ArrayList<T> items = new ArrayList<T>();
    		callback.callback(t, RFAT.GET_SINGLE, items);
        }
    }
	
	private class DeleteItemTask extends AsyncTask<String, Void, String> {
    	@Override
        protected String doInBackground(String... urls) {

            try {
            	return RESTfulConnect.deleteResource(urls[0], urls[1], urls[2]);
            } catch (IOException e) {
            	e.printStackTrace();
            	return "Connection Error";
            }
        }
    	@SuppressWarnings("unchecked")
		@Override
        protected void onPostExecute(String result) {
    		T t = (T)presenter.getEmptyEntity();
    		modalDialog.dismiss();
    		ArrayList<T> items = new ArrayList<T>();
    		callback.callback(t, RFAT.DELETE, items);
        }
    }
	
	private class UpdateItemTask extends AsyncTask<String, Void, String> {
    	@Override
        protected String doInBackground(String... urls) {
            try {
                return RESTfulConnect.putResource(urls[0], urls[1], urls[2], urls[3]);
            } catch (IOException e) {
            	e.printStackTrace();
            	return "Connection Error";
            }
        }
    	@SuppressWarnings("unchecked")
		@Override
        protected void onPostExecute(String result) {
    		modalDialog.dismiss();
    		ArrayList<T> items = new ArrayList<T>();
    		T t = (T)presenter.getEmptyEntity();
    		callback.callback(t, RFAT.UPDATE, items);
        }
    }
	
	private class InsertItemTask extends AsyncTask<String, Void, String> {
    	@Override
        protected String doInBackground(String... urls) {
            try {
                return RESTfulConnect.postResource(urls[0], urls[1], urls[2], urls[3]);
            } catch (IOException e) {
            	e.printStackTrace();
            	return "Connection Error";
            }
        }
    	@SuppressWarnings("unchecked")
		@Override
        protected void onPostExecute(String result) {
    		try{
	    		modalDialog.dismiss();
	    		ArrayList<T> items = new ArrayList<T>();
	    		if(result.subSequence(0, 2).equals("<?")){
	    			T t = (T)presenter.tryJSONParse(result);
		    		callback.callback(t, RFAT.INSERT, items);
	    		} else {
	    			JSONObject json = new JSONObject(result);
	    			T t = (T)presenter.createItemFromJSONObject(json);
		    		callback.callback(t, RFAT.INSERT, items);
	    		}
    		} catch(JSONException ex){
    			ex.printStackTrace();
    		} 
        }
    }
}
